package com.youhome.service.service.impl;

import cn.jiguang.common.resp.APIConnectionException;
import cn.jiguang.common.resp.APIRequestException;
import cn.jsms.api.JSMSClient;
import cn.jsms.api.SendSMSResult;
import cn.jsms.api.common.SMSClient;
import cn.jsms.api.common.model.BatchSMSPayload;
import cn.jsms.api.common.model.BatchSMSResult;
import cn.jsms.api.common.model.RecipientPayload;
import cn.jsms.api.common.model.SMSPayload;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.youhome.common.config.SMSConfig;
import com.youhome.common.exception.CustomException;
import com.youhome.common.response.Result;
import com.youhome.common.response.ResultCode;
import com.youhome.service.mapper.BSendRecordSMSGatherMapper;
import com.youhome.service.mapper.BSendRecordSMSMapper;
import com.youhome.service.mapper.BTemplateSMSMapper;
import com.youhome.service.mapper.BUserMapper;
import com.youhome.service.model.*;
import com.youhome.service.response.Param;
import com.youhome.service.response.SMS;
import com.youhome.service.service.*;
import com.youhome.utils.JsonUtils;
import com.youhome.utils.ValidationUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * Created by chen365 on 2017/12/15.
 */
@Service
@Slf4j
public class SMSServiceImpl implements SMSService {

    @Autowired
    private SMSConfig smsConfig;
    @Autowired
    private BUserService bUserService;
    @Autowired
    private BShareGroupService bShareGroupService;
    @Autowired
    private BCounselorService bCounselorService;
    @Autowired
    private BClientService bClientService;
    @Autowired
    private BSendRecordSMSMapper bSendRecordSMSMapper;
    @Autowired
    private BTemplateSMSMapper bTemplateSMSMapper;
    @Autowired
    private BSendRecordSMSGatherMapper bSendRecordSMSGatherMapper;
    @Autowired
    private BUserMapper bUserMapper;

    @Override
    public int notice(Integer type, Long id, String name, String phone) {
        BUser user = new BUser();
        if (type == 1) {//通知顾问
            user = bUserMapper.selectByCounselorId(id);
        } else if (type == 2) { //通知管理员
            user = bUserMapper.selectByCompanyId(id);
        } else {

        }

        SMSClient client = new SMSClient(smsConfig.getSecret(), smsConfig.getAppkey());
        SMSPayload payload = SMSPayload.newBuilder()
                .setMobileNumber(user.getPhone())
                .setTempId(147701)
                .addTempPara("name", name)
                .addTempPara("phone", phone)
                .build();
        try {
            SendSMSResult res = client.sendTemplateSMS(payload);
            log.info(res.toString());
        } catch (APIRequestException e) {
            log.error("Error response from JPush server. Should review and fix it. ", e);
            log.info("HTTP Status: " + e.getStatus());
            log.info("Error Message: " + e.getMessage());
        } catch (APIConnectionException e) {
            log.error("Connection error. Should retry later. ", e);
        }

        return 1;
    }

    @Override
    @Transactional
    public int send(Long userId, Integer tempId, List<SMS> smss) throws CustomException {

        SMSClient client = new SMSClient(smsConfig.getSecret(), smsConfig.getAppkey());
        BTemplateSMS templateSMS = bTemplateSMSMapper.selectByPrimaryKey(Long.valueOf(tempId));

        Integer type = templateSMS.getType();

        BSendRecordSMSGather bSendRecordSMSGather = new BSendRecordSMSGather();
        bSendRecordSMSGather.setParam(JSON.toJSON(smss).toString());
        bSendRecordSMSGather.setCount(smss.size());
        bSendRecordSMSGather.setTempId(templateSMS.getId());
        bSendRecordSMSGather.setTempName(templateSMS.getName());
        bSendRecordSMSGather.setTemplate(templateSMS.getTemplate());
        bSendRecordSMSGather.setCtime(new Date());
        bSendRecordSMSGather.setUserId(userId);

        bSendRecordSMSGatherMapper.insertSelective(bSendRecordSMSGather);

        BSendRecordSMS bSendRecordSMS = new BSendRecordSMS();
        bSendRecordSMS.setUserId(userId);
        System.err.println("bSendRecordSMSGather.getId():" + bSendRecordSMSGather.getId());
        bSendRecordSMS.setGatherId(bSendRecordSMSGather.getId());

        for (SMS sms : smss) {
            String template = templateSMS.getTemplate();
            String regex = "\\{\\{[^\\}]*\\}\\}";
            Pattern pattern = Pattern.compile(regex);
            Matcher match = pattern.matcher(templateSMS.getTemplate());

            String name = null;

            while (match.find()) {
                List<Param> params = sms.getParams();
                for (Param param : params) {
                    if (param.getName().equals("name")) {
                        name = param.getValue();
                    }
                    template = template.replace("{{" + param.getName() + "}}", param.getValue());
                }
            }
            int consume = 1;
            template = template.trim();
            consume = (int) Math.ceil(template.length() / 70); //每条短信长度为70个字符

            bSendRecordSMS.setType(String.valueOf(type));
            bSendRecordSMS.setName(name);
            bSendRecordSMS.setPhone(sms.getPhone());
            bSendRecordSMS.setSms(template);
            bSendRecordSMS.setConsume(consume);
            bSendRecordSMS.setCtime(new Date());
            bSendRecordSMS.setStatus(0);

            SMSPayload.Builder newBuilder = new SMSPayload.Builder();

            newBuilder.setMobileNumber(sms.getPhone());
            newBuilder.setTempId(tempId);

            List<Param> params = sms.getParams();
            for (Param param : params) {
                newBuilder.addTempPara(param.getName(), param.getValue());
            }
            SMSPayload payload = newBuilder.build();

            try {
                SendSMSResult res = client.sendTemplateSMS(payload);
                if (res.isResultOK()) {
                    bSendRecordSMS.setStatus(1);
                    bSendRecordSMS.setConsume(1);
                }
                log.info(res.toString());
            } catch (APIRequestException e) {
                log.error("Error response from JPush server. Should review and fix it. ", e);
                log.info("HTTP Status: " + e.getStatus());
                log.info("Error Message: " + e.getMessage());
                //throw new CustomRuntimeException(e.getStatus(), e.getMessage());
                return 0;
            } catch (APIConnectionException e) {
                log.error("Connection error. Should retry later. ", e);
                //throw new CustomRuntimeException(e.getStatus(), e.getMessage());
                return 0;

            }

            if (bSendRecordSMSMapper.insertSelective(bSendRecordSMS) == 0) {
                throw new CustomException(ResultCode.FAIL);
            }
        }

        return 1;
    }


    @Override
    public String getSMSCode(String type, String phone, String shareId) throws CustomException {


        if (!ValidationUtils.isPhone(phone)) {
            throw new CustomException(ResultCode.ERROR_PHONE);
        }
        if (StringUtils.isEmpty(type)) {
            throw new CustomException(ResultCode.EMPTY_SMS_TYPE);
        }
        if (type.equalsIgnoreCase("register")) {
            if (bUserService.selectByPhone(phone) != null) {
                throw new CustomException(ResultCode.REGISTERED_PHONE);
            }
        } else if (type.equalsIgnoreCase("login")) {
            if (bUserService.selectByPhone(phone) == null) {
                throw new CustomException(ResultCode.UNREGISTERED_PHONE);
            }
        } else if (type.equalsIgnoreCase("client")) {
            BShareGroup shareGroup = bShareGroupService.selectByPrimaryKey(shareId);
            if (shareGroup == null) {
                throw new CustomException(ResultCode.COUNSELOR_INEXISTENCE);
            }
            BCounselor counselor = bCounselorService.selectByPrimaryKey(shareGroup.getCounselorId());
            if (counselor == null) {
                throw new CustomException(ResultCode.COUNSELOR_INEXISTENCE);
            }
            if (bClientService.isExist(phone, counselor.getCompanyId()) > 0) {
                throw new CustomException(ResultCode.CLIENT_REGISTERED_WITH_COUNSELOR);
            }
        }
        JSMSClient jsmsClient = new JSMSClient(smsConfig.getSecret(), smsConfig.getAppkey());
        SMSPayload payload = SMSPayload.newBuilder().setMobileNumber(phone).setTTL(smsConfig.getTtl()).setTempId(smsConfig.getTempId()).build();
        SendSMSResult result = null;
        try {
            result = jsmsClient.sendSMSCode(payload);
        } catch (APIConnectionException e) {
            e.printStackTrace();
            throw new CustomException(ResultCode.FAIL, e.getMessage());
        } catch (APIRequestException e) {
            e.printStackTrace();
            throw new CustomException(ResultCode.FAIL, e.getErrorMessage());
        }
        if (result.isResultOK()) {
            return result.getMessageId().toString();
        } else {
            throw new CustomException(ResultCode.FAIL, result.getOriginalContent());
        }
    }

    @Override
    public void send(Principal principal,Integer tempId, String smss) throws CustomException {
        Long userId = principal.getUser().getUserId();

        if (StringUtils.isEmpty(tempId)) {
            throw new CustomException(ResultCode.NO_SMS_TEMPLATE);
        }
        if (StringUtils.isEmpty(smss)) {
            throw new CustomException(ResultCode.ERROR_PARAMETER);
        }

        List<SMS> list = JsonUtils.json2List(smss, SMS.class);
        if (send(userId, tempId, list) <= 0) {
            throw new CustomException(ResultCode.FAIL);
        }
    }

    @Override
    public PageInfo<BSendRecordSMS> selectByBean(Principal principal,Long gatherId, Integer pageNumber, Integer pageSize) throws CustomException {
        Long userId = principal.getUser().getUserId();

        if (StringUtils.isEmpty(gatherId)) {  //记录集Id
            throw new CustomException(ResultCode.ERROR_PARAMETER);
        }

        if (pageNumber == null || pageNumber < 1) {
            pageNumber = 1;
        }
        if (pageSize == null || pageSize < 1) {
            pageSize = 10;
        }

        BSendRecordSMS bSendRecordSMS = new BSendRecordSMS();

        bSendRecordSMS.setUserId(userId);
        bSendRecordSMS.setGatherId(gatherId);

        PageHelper.startPage(pageNumber, pageSize);
        List<BSendRecordSMS> list = bSendRecordSMSMapper.selectByBean(bSendRecordSMS);
        return new PageInfo<>(list);
    }

    @Override
    public String getSMSCode(String phone) throws CustomException {
        try {
            if (!ValidationUtils.isPhone(phone)) {
                throw new CustomException(ResultCode.ERROR_PHONE);
            }
            JSMSClient jsmsClient = new JSMSClient(smsConfig.getSecret(), smsConfig.getAppkey());
            SMSPayload payload = SMSPayload.newBuilder().setMobileNumber(phone).setTTL(300).setTempId(107224).build();
            SendSMSResult result = jsmsClient.sendSMSCode(payload);
            if (result.isResultOK()) {
                return result.getMessageId().toString();
            } else {
                throw new CustomException(ResultCode.FAIL, result.getOriginalContent());
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new CustomException(ResultCode.FAIL);
        }
    }

    /**
     * 批量发短信
     *
     * @param tempId
     * @param smss
     */
    public void batchSendSMS(Integer tempId, List<SMS> smss) {
        SMSClient client = new SMSClient(smsConfig.getSecret(), smsConfig.getAppkey());
        List<RecipientPayload> list = new ArrayList<RecipientPayload>();
        for (SMS sms : smss) {
            RecipientPayload.Builder builder = new RecipientPayload.Builder();
            builder.setMobile(sms.getPhone());

            List<Param> params = sms.getParams();
            for (Param param : params) {
                builder.addTempPara(param.getName(), param.getValue());
            }
            RecipientPayload recipientPayload = builder.build();
            list.add(recipientPayload);
        }

        RecipientPayload[] recipientPayloads = new RecipientPayload[list.size()];
        BatchSMSPayload smsPayload = BatchSMSPayload.newBuilder()
                .setTempId(tempId)
                .setRecipients(list.toArray(recipientPayloads))
                .build();
        try {
            BatchSMSResult result = client.sendBatchTemplateSMS(smsPayload);
            log.info("Got result: " + result);
        } catch (APIConnectionException e) {
            log.error("Connection error. Should retry later. ", e);
        } catch (APIRequestException e) {
            log.error("Error response from JPush server. Should review and fix it. ", e);
            log.info("HTTP Status: " + e.getStatus());
            log.info("Error Message: " + e.getMessage());
        }
    }
}
